﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using D2D2.Server.Networking;
using D2D2.SharedInterfaces.Networking;
using Lidgren.Network;
using Microsoft.Xna.Framework;

namespace D2D2.Server.Core
{

    public class MonsterManagerServer
    {
        private Dictionary<long, List<MonsterObject>> _monstersHistory = new Dictionary<long, List<MonsterObject>>();
 
        private List<MonsterObject> _monsters = new List<MonsterObject>();
        private long _monsterCounter = 0;
       // private float _updateTime = 0;
        //private const float UPDATE_LATENCY=0.1f;
        private ServerManager _serverManager;
        
        public MonsterManagerServer(ServerManager serverManager, DropManagerServer dropManager)
        {
            _serverManager = serverManager;
        }

        public MonsterObject AddMonster(MonsterType type, MonsterView view, int level, Vector2 location)
        {
            MonsterObject monster = new MonsterObject();
            long id = Interlocked.Increment(ref _monsterCounter);

            monster.Id = id;
            monster.MonsterType = type;
            monster.MonsterView = view;
            monster.Level = level;
            monster.Location = location;
            monster.HitTime = 0.3f;
            Calculate(monster);
            monster.CurrentLive = monster.TotalLive;

            _monsters.Add(monster);

            List<MonsterObject> historyList = new List<MonsterObject>();
            _monstersHistory.Add(monster.Id, historyList);

            return monster;
        }

        public void Update(float elapsed)
        {
            foreach (MonsterObject monster in Monsters)
            {
                bool needUpdate = monster.CalculateLive(elapsed);
                if (monster.HasResponse)
                {
                    PlayerObject player = monster.TargetPlayer;
                    player.DecreaseLive(monster.GetDamage());
                    _serverManager.SendMessage(player);

                    monster.HasResponse = false;
                }

                //if (needUpdate)
                    _serverManager.SendMessage(monster);

                monster.MessageTime = NetTime.Now;

                List<MonsterObject> history = _monstersHistory[monster.Id];
                history.Add(monster.Clone());
                if (history.Count > 30) history.RemoveAt(0);
            }

            _monsters = _monsters.FindAll(m => m.Alive);
        }

        public void Hit(PlayerObject player, MonsterObject monster, double messageTime)
        {
            
            List<MonsterObject> history = _monstersHistory[monster.Id];


            List<MonsterObject> before = history.FindAll(m => m.MessageTime < messageTime);
            if (before.Any())
            {
                MonsterObject historyMonster = before[before.Count - 1];

                
               // Console.WriteLine(string.Format("Current live: {0}. Immune: {1}", historyMonster.CurrentLive,
                //                                historyMonster.InDecreasingHit));

                if (historyMonster.InDecreasingHit)
                    return;
            }
        

            monster.Hit(player, messageTime);
        }

        public List<MonsterObject> Monsters
        {
            get { return _monsters; }
        }

        public void Refresh()
        {
            _monsters = _monsters.FindAll(m => m.CurrentLive > 0);
        }

        private void Calculate(MonsterObject monster)
        {
            monster.TotalLive = monster.Level*10*(int) monster.MonsterType;
            monster.MinDamage = monster.Level*3*(int) monster.MonsterType;
            monster.MaxDamage = monster.Level*6*(int) monster.MonsterType;
            monster.LiveRegen =(float) monster.Level*(float) monster.MonsterType;
        }
    }
}
